06 Before or After and OCC
Before or After
系统允许并发执行;但并发执行得到的结果和串行执行相同。
锁
global lock
任何时间,只有一个事务允许执行,相当于串行。
fine-grained locking
希望锁越多越好,不同的数据对应不同的锁。同一数据串行,不同数据并行。
然而,这种细粒度控制仍然可能出现race condition等问题。
2PL
拿锁和放锁分为两个阶段。具体来说,开始放锁之后,就不允许新拿到任何锁。
可串行化
- 视图可串行化
- 每个读取的初始值相同
- 每个读操作依赖同一个写操作
- 最终每个写操作来自同一个事务
- 冲突可串行化
- 不同事务操作同一数据,且有一个是写操作,即冲突
- 通过图来判断,无环则可串行
- 顺序一致性
冲突可串行化属于视图可串行化。判断是否为视图可串行化属于NP hard问题。
幻影问题
在遍历同时插入,可能会导致冲突;只给具体的数据加锁无法解决这个问题。
理论上可以用谓词锁解决;任何两个冲突的操作都需要加锁。但实际上,这种问题一般被无视。
OCC
- 并发本地处理
- 将数据读到读集合中
- 将数据写到buffer中
- 在临界区验证可串行化
- 提交/中止
不同的事务可能对数据进行相同的修改,因此要引入版本号。
- phase 1
- 将数据读到读集合中:同时读数据和版本号
- 将数据写到buffer中:更新write后还需要更新read
- phase 2 验证可串行化:通过版本号确认是否改变
- phase 3
- 如果read-set中的数据被修改/上锁,中止
- 提交
phase2和3不能拆开。
OCC可以避免2PL的问题。由于在操作全部执行后才提交,OCC可以将拿锁顺序排序,避免2PL的死锁。此外,OOC还可以将read-set的锁去掉。